package com.tjbank.cssys.service.config.shiro;

import com.tjbank.cssys.service.config.shiro.stateless.filter.StatelessAuthcFilter;
import com.tjbank.cssys.service.config.shiro.stateless.realms.StatelessTokenRealm;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.*;

/**
 * Copyright © 天阳宏业科技股份有限公司 - All Rights Reserved
 *
 * @description: shiro的自定义配置,其他内置配置已通过shiro-spring-boot-starter加载.
 * @author: <a href="mailto:guzheng01@tansun.com.cn>Joey Gu</a>
 * @date: 2020-06-08 17:22
 **/
@Configuration
public class ShiroConfig {

    /**
     * 登录的URL
     */
    @Value("${shiro.loginUrl}")
    private String loginUrl;

    /**
     * 登录成功后的URL
     */
    @Value("${shiro.successUrl}")
    private String successUrl;

    /**
     * 未授权的URL
     */
    @Value("${shiro.unauthorizedUrl}")
    private String unauthorizedUrl;

    @Value("${shiro.filterChainDefinitions}")
    private String filterChainDefinitions;

    /**
     * shiro管理的Bean的生命周期.
     * @return LifecycleBeanPostProcessor
     */
    static @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 登录成功后要跳转的连接
        shiroFilterFactoryBean.setSuccessUrl(successUrl);
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);

        Map<String, Filter> filters = new HashMap<>(16);
        // 可以增加其他的Filter
        filters.put("statelessAuthc", statelessAuthcFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 拦截器
        FilterChainDefinitionMap chains = new FilterChainDefinitionMap();
        chains.setFilterChainDefinitions(filterChainDefinitions);

        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        shiroFilterFactoryBean.setFilterChainDefinitionMap(chains.getObject());
        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        // 设置realm.
        securityManager.setAuthenticator(modularRealmAuthenticator());
        // 设置了sessionManager之后，httpSession默认由shiro session代理 各种session获取不到
        /// securityManager.setSessionManager(sessionManager());
        // 多个realm 添加到securityManager的管理之下.
        List<Realm> realms = new ArrayList<>();
        realms.add(statelessTokenRealm());
        /// realms.add(usernamePasswordRealm());
        /// realms.add(nothingToDoRealm());
        securityManager.setRealms(realms);

        return securityManager;
    }


    /**
     * 让spring管理的realm Bean
     */
    @Bean
    public StatelessTokenRealm statelessTokenRealm() {
        StatelessTokenRealm tokenRealm = new StatelessTokenRealm();
        tokenRealm.setCachingEnabled(false);
        return tokenRealm;
    }

    /**
     * 如果有多个realm，会使用这个来选择策略，进行调度，判断realm的权限校验是否通过
     *
     * @return ModularRealmAuthenticator
     */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator() {
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        // 只要有一个realm成功，就放行，并且不继续判断realm
        modularRealmAuthenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
        return modularRealmAuthenticator;
    }


    @Bean
    public StatelessAuthcFilter statelessAuthcFilter() {
        return new StatelessAuthcFilter();
    }

    /**
     * 设置statelessAuthcFilter filter不自动注册到spring管理的监听器中，防止与shiro filter同级，导致该监听器必定执行
     * @param statelessAuthcFilter  无状态权限过滤器
     * @return statelessAuthcFilterRegister
     */
    @Bean
    @SuppressWarnings("rawtypes")
    public FilterRegistrationBean registerStatelessAuthcFilter(@Autowired StatelessAuthcFilter statelessAuthcFilter) {
        FilterRegistrationBean<StatelessAuthcFilter> statelessAuthcFilterRegister = new FilterRegistrationBean<>(statelessAuthcFilter);
        statelessAuthcFilterRegister.setEnabled(false);

        return statelessAuthcFilterRegister;
    }

//    @Bean
//    public UsernamePasswordRealm usernamePasswordRealm() {
//        return new UsernamePasswordRealm();
//    }
//
//    @Bean
//    public NothingToDoRealm nothingToDoRealm() {
//        return new NothingToDoRealm();

//   }


}
